﻿#region Creditos

/* Autor: Edilberto Sánchez Forero	*/
/* Email: esanchezfo@gmail.com		*/
/* Licencia: LGPL, Software Libre	*/
/* País: Colombia, Bogotá			*/

#endregion

#region Librerias

using System;
using System.Text;
using System.IO;
using System.Data.Common;
using System.Data;
using System.Collections.Generic;

using ESF.General;
using ESF.Object.XmlRepresenter.Rules;
using ESF.Object.XmlRepresenter;
using ESF.General.Text;

#endregion


namespace ESF.Object.DataBaseGenerator
{
	public class MySqlDbGenerator : DbGenerator
	{
		#region Constantes
		
		private const byte NUMERIC_MAXLENGTH = 65;
		
		private const string NAMES_SEPARATOR = "`";
		private const char COMMENTS_SEPARATOR = '-';
		private const string PARAMS_SEPARATOR = "";
		private const string VARS_SEPARATOR = "@";
		
		#endregion
		
	
		#region Constructor
		
		public MySqlDbGenerator (string pstrDataBaseName, string pstrConnectionStringName, XmlObjectSetManager pobjObjectSetManager)
			: base (DbProviders.MySql, pstrDataBaseName.ToLower (), pstrConnectionStringName, pobjObjectSetManager,
				MySqlDbGenerator.NAMES_SEPARATOR, MySqlDbGenerator.COMMENTS_SEPARATOR, 
				MySqlDbGenerator.PARAMS_SEPARATOR, MySqlDbGenerator.VARS_SEPARATOR) { }
			
		#endregion
		
		
		#region Base de Datos
		
		protected override void AddDeleteDataBase ()
		{
			this._Writer.Write ("DROP DATABASE IF EXISTS {0}{1}{0};", this.NamesSeparator, this.DataBaseName);
		}
				
		
		protected override void AddCreateDataBase ()
		{
			this._Writer.Write ("CREATE DATABASE IF NOT EXISTS {0}{1}{0};", this.NamesSeparator, base.DataBaseName);
		}
		
		#endregion
		
		
		#region Tablas

		protected override string GenerateTableName(XmlObject pobjObject)
		{
			return string.Format ("{0}{1}{0}.{0}{2}_{3}{0}", this.NamesSeparator, base.DataBaseName, pobjObject.SetName, pobjObject.Name);
		}


		protected override string GenerateTableNameForRefArray(XmlObject pobjObject, XmlMember pobjMember, XmlObject pobjExtRefObject)
		{
			return string.Format (string.Format ("{0}{1}{0}.{0}{2}_{3}_{4}_{5}_{6}{0}", this.NamesSeparator, this.DataBaseName, 
				pobjObject.SetName, pobjObject.Alias, pobjMember.Alias, pobjExtRefObject.SetName, pobjExtRefObject.Alias));
		}
		
		
		private string GenerateNumericInfo (byte? pbytNumericPrecision, byte? pbytNumericScale)
		{
			string strResult;
			
			
			strResult = string.Empty;
		
			if (pbytNumericPrecision != null)
			{
				strResult += string.Format (" ({0}", pbytNumericPrecision.Value.ToString ());
				
				if (pbytNumericScale != null)
				{
					strResult += string.Format (", {0}", pbytNumericScale.Value.ToString ());
				}
				
				strResult += ")";
			}
			
			return strResult;
		}
		
		
		protected override void AddDeleteTable (XmlObject pobjObject)
		{
			this.AddDeleteTable (this.GenerateTableName (pobjObject));
		}
		
		
		protected override void AddDeleteTable (string pstrTableName)
		{
			this._Writer.Write ("DROP TABLE IF EXISTS {0};", pstrTableName);
		}


		protected override void AddStartTable (ref StringBuilder pstbSql, XmlObject pobjObject)
		{
			string strTableName;
		
		
			strTableName = this.GenerateTableName (pobjObject);
		
			this.AddComment (ref pstbSql, string.Format ("Creación de la Tabla: {0}", strTableName));
		
			pstbSql.AppendFormat ("CREATE TABLE IF NOT EXISTS {0}", strTableName);
			pstbSql.Append (TextHelper.NL_PO);
		}


		protected override void AddStartTableForRefArray(ref StringBuilder pstbSql, XmlObject pobjObject, XmlMember pobjMember, XmlObject pobjRefObject)
		{
			string strTableName;
		
		
			strTableName = this.GenerateTableNameForRefArray (pobjObject, pobjMember, pobjRefObject);
		
			this.AddComment (ref pstbSql, string.Format ("Creación de la Tabla: {0}", strTableName));
			
			pstbSql.AppendFormat ("CREATE TABLE IF NOT EXISTS {0}", strTableName);
			pstbSql.Append (TextHelper.NL_PO);
		}

		#endregion
		
		
		#region Columnas

		protected override string GenerateTraslateDbType (XmlMember pobjMember)
		{
			XmlObject objRef;
		
		
			if (pobjMember.Type == ValueTypes.Custom)
			{
				objRef = this.ObjectSetManager.GetObjectBy (pobjMember);
			
				if (!objRef.IsArray)
				{
					return this.GenerateTraslateDbType ((ValueTypes) objRef.IDType, objRef.IDMaxLength, null, null);	
				}
			}
			else
			{
				return this.GenerateTraslateDbType (pobjMember.Type.Value, pobjMember.ApplicableMaxLength, pobjMember.NumericPrecision, pobjMember.NumericScale);
			}
			
			return string.Empty;
		}
		
		
		protected override string GenerateTraslateDbType
		(
			ValueTypes pobjValueType, ushort? pshrApplicableMaxLength, 
			byte? pbytNumericPrecision, byte? pbytNumericScale
		)
		{
			string strResult;
			
		
			switch (pobjValueType)
 			{
 				case ValueTypes.Guid:
 					strResult = "VARCHAR (" + TextHelper.GUID_LENGTH + ")";
 					break;
 			
 				case ValueTypes.Bool:
 					strResult = "BOOLEAN";
 					break;
 				
 				case ValueTypes.SByte:
 					strResult = "TINYINT"; 			
 					strResult += this.GenerateNumericInfo (pbytNumericPrecision, pbytNumericScale); 					
 					break;
 				
 				case ValueTypes.Byte:
 					strResult = "TINYINT"; 					
 					strResult += this.GenerateNumericInfo (pbytNumericPrecision, pbytNumericScale); 
 					strResult += " UNSIGNED";
 					break;
 					
 				case ValueTypes.Date:
 					strResult = "DATE";
 					break;
 					
 				case ValueTypes.DateTime:
 					strResult = "DATETIME";
 					break;
 					
 				case ValueTypes.Decimal: 
 					strResult = "DECIMAL";
 					strResult += this.GenerateNumericInfo (pbytNumericPrecision, pbytNumericScale);
 					break;
 					
 				case ValueTypes.Double:
 					strResult = "DOUBLE";
 					strResult += this.GenerateNumericInfo (pbytNumericPrecision, pbytNumericScale);
 					break;
 					
 				case ValueTypes.Float:
 					strResult = "FLOAT";
 					strResult += this.GenerateNumericInfo (pbytNumericPrecision, pbytNumericScale);
 					break;
 					
 				case ValueTypes.Int32:
 					strResult = "MEDIUMINT";
 					strResult += this.GenerateNumericInfo (pbytNumericPrecision, pbytNumericScale);
 					break;
 					
 				case ValueTypes.Int64:
 					strResult = "BIGINT";
 					strResult += this.GenerateNumericInfo (pbytNumericPrecision, pbytNumericScale);
 					break;
 					
 				case ValueTypes.Int16:
 					strResult = "SMALLINT";
 					break;
 					
 				case ValueTypes.UInt32:
 					strResult = "MEDIUMINT";
 					strResult += this.GenerateNumericInfo (pbytNumericPrecision, pbytNumericScale);
 					strResult += " UNSIGNED";
 					break;
 					
 				case ValueTypes.UInt64:
 					strResult = "BIGINT";
 					strResult += this.GenerateNumericInfo (pbytNumericPrecision, pbytNumericScale);
 					strResult += " UNSIGNED";
 					break;
 					
 				case ValueTypes.UInt16:
 					strResult = "SMALLINT";
 					strResult += this.GenerateNumericInfo (pbytNumericPrecision, pbytNumericScale);
 					strResult += " UNSIGNED";
 					break;
 					
 				case ValueTypes.String:
 					if (pshrApplicableMaxLength == null)
 					{
 						strResult = "TEXT";
 					}
 					else
 					{
 						strResult = string.Format ("VARCHAR ({0})", pshrApplicableMaxLength);
 					} 
 					break;
 					
 				default:
 					
 					// TODO: Revisar para soportar arreglos de bytes, el sbyte, y otros no incluidos
 					throw new NotSupportedException (string.Format ("Para el tipo proporcionado no se ha realizado la traducción a Sql: {0}", pobjValueType));
 			}
 			
 			return strResult;
		}


		protected override string GenerateTraslateDbIDType (IDTypes? pobjIDType, byte? pbytIDMaxLength)
		{
			string strResult;
			
			
			if (pobjIDType == IDTypes.String)
			{
				strResult = "VARCHAR";
				
				if (pbytIDMaxLength != null)
				{
					strResult += string.Format (" ({0})", pbytIDMaxLength);
				}
				
				return strResult;
			}
			
		
			switch (pobjIDType)
			{
				case IDTypes.Byte:
					strResult = "TINYINT";
					break;
					
				case IDTypes.UInt32:
					strResult = "MEDIUMINT";
					break;
					
				case IDTypes.UInt16:
					strResult = "SMALLINT";
					break;
					
				default:
					strResult = "BIGINT";
					break;
			}
			
			if (pbytIDMaxLength != null)
			{
				strResult += string.Format (" ({0})", pbytIDMaxLength);
			}
			
			return strResult + " UNSIGNED";
		}

		
		protected override void AddColumn (ref StringBuilder pstbSql, XmlMember pobjMember)
		{
 			pstbSql.AppendFormat ("{0}{1}{0} {2}", this.NamesSeparator, pobjMember.Name,
 				this.GenerateTraslateDbType (pobjMember));
 			
 			if (pobjMember.Required) { pstbSql.Append (" NOT NULL"); }
		}


		protected override void AddPrimaryKeyColumn (ref StringBuilder pstbSql, IDTypes pobjIDType, byte? pbytIDMaxLength)
		{
			pstbSql.AppendFormat ("{0}ID{0} {1}", this.NamesSeparator,
				this.GenerateTraslateDbIDType (pobjIDType, pbytIDMaxLength));
			
			if (pobjIDType != IDTypes.String)
			{
				pstbSql.Append (" NOT NULL AUTO_INCREMENT");
			}
		}


		protected override void AddPrimaryKeyConstraint (ref StringBuilder pstbSql)
		{
			pstbSql.AppendFormat ("PRIMARY KEY ({0}ID{0})", this.NamesSeparator);
		}


		protected override void AddForeignConstraint 
		(
			ref StringBuilder pstbSql, 
			XmlObject pobjRefObject, XmlObject pobjObject
		)
		{
			// Referencia al ID objeto
			pstbSql.AppendFormat ("CONSTRAINT {0}FK_{1}_{2}{0} FOREIGN KEY ({0}ID{3}{0}) REFERENCES {4} ({0}ID{0})", 
				this.NamesSeparator, pobjRefObject.Alias, pobjObject.Alias, pobjObject.Name, this.GenerateTableName (pobjObject));
		}
		
		
		protected override void AddForeignConstraint 
		(
			ref StringBuilder pstbSql, 
			XmlObject pobjRefObject, XmlMember pobjMember, XmlObject pobjExtRefObject
		)
		{
			pstbSql.AppendFormat ("CONSTRAINT {0}FK_{2}_{3}_{4}{0} FOREIGN KEY ({0}ID{1}{0}) REFERENCES {5} ({0}ID{0})", 
				this.NamesSeparator, pobjExtRefObject.Name, pobjRefObject.Alias, 
				pobjExtRefObject.Alias, pobjMember.Alias, this.GenerateTableName (pobjExtRefObject));
		}
		
		
		protected override void AddForeignColumn
		(
			ref StringBuilder pstbSql, XmlObject pobjObject
		)
		{
			pstbSql.AppendFormat ("{0}ID{1}{0} {2}", this.NamesSeparator, pobjObject.Name, 
				this.GenerateTraslateDbType ((ValueTypes) pobjObject.IDType, pobjObject.IDMaxLength, null, null));
		}
		
		
		protected override void AddForeignColumn
		(
			ref StringBuilder pstbSql, 
			XmlMember pobjMember, XmlObject pobjExtRefObject
		)
		{
			pstbSql.AppendFormat ("{0}ID{1}{0} {2}", this.NamesSeparator, pobjMember.Name, 
				this.GenerateTraslateDbType ((ValueTypes) pobjExtRefObject.IDType, pobjExtRefObject.IDMaxLength, null, null));
		}
		

		protected override void AddOnlyOneConstraint (ref StringBuilder pstbSql, OnlyOneRule pobjOnlyOneRule)
		{
			// TODO: Completar soporte a un trigger ajustado, previo ajuste de la definicion de la regla
		}


		protected override void AddEndTable (ref StringBuilder pstbSql)
		{
			pstbSql.Append (TextHelper.NL_PC);
			pstbSql.AppendLine (";\n");
		}


		protected override void AddAlterUniqueConstraint (ref StringBuilder pstbSql, XmlObject pobjObject, string pstrUniqueName, string [] pstrColumnNames)
		{
			pstbSql.AppendFormat ("ALTER TABLE {1} ADD UNIQUE INDEX {0}IX_{2}{0} (", 
				this.NamesSeparator, this.GenerateTableName (pobjObject), pstrUniqueName);
			
			foreach (string pstrColumnName in pstrColumnNames)
			{
				pstbSql.AppendFormat ("{0}{1}{0},", this.NamesSeparator, pstrColumnName);
			}
							
			pstbSql.Length --;

			pstbSql.AppendLine (");");
		}
		
		
		protected override void AddAlterUniqueConstraint (ref StringBuilder pstbSql, XmlObject pobjObject, XmlMember pobjMember, XmlObject pobjRefObject, XmlObject pobjExtRefObject)
		{
			pstbSql.AppendFormat ("ALTER TABLE {1} ADD UNIQUE INDEX {0}IX_{2}.{3}{0} ", 
				this.NamesSeparator, this.GenerateTableNameForRefArray (pobjObject, pobjMember, pobjRefObject), pobjObject.Alias, pobjRefObject.Alias);
			
			pstbSql.AppendFormat ("({0}ID{1}{0},", this.NamesSeparator, pobjMember.Object.Name);
			pstbSql.AppendFormat ("{0}ID{1}{0});", this.NamesSeparator, pobjExtRefObject.Name);
		}
		
		#endregion
		
		
		#region Procedimientos Almacenados

		#region Eliminacion

		protected override void AddDeleteSP (string pstrSPName)
		{
 			this._Writer.WriteLine ("DROP PROCEDURE IF EXISTS {0};", pstrSPName);
		}
		
		#endregion
		
		#region Encabezados y Fin de procedimiento
		
		protected override void AddStartSP (XmlObject pobjObject, string pstrOperationName)
		{
			this._Writer.WriteLine ("DELIMITER $$");
			this._Writer.Write ("CREATE PROCEDURE {0}", this.GenerateSPName (pobjObject, pstrOperationName));
			this._Writer.Write (TextHelper.NL_PO);
		}


		protected override void AddEndSP()
		{
			this._Writer.WriteLine ();
			this._Writer.WriteLine ();
			this._Writer.WriteLine ("END $$");
			this._Writer.WriteLine ("DELIMITER ;"); 
			this._Writer.WriteLine ();
			this._Writer.WriteLine ();
		}
		
		#endregion

		#region Creacion

		private string GenerateObjectParameters (XmlObject pobjObject)
		{
			string strTemp;
		
			StringBuilder stbResult;
			
			
			stbResult  = new StringBuilder ();
			
			stbResult.Append (TextHelper.NL_1_TAB);
			stbResult.Append (this.GenerateSPParameterID (pobjObject.IDType, pobjObject.IDMaxLength));
			stbResult.Append (TextHelper.NL_1_TAB);
			stbResult.Append (",");
			stbResult.Append (this.GenerateSPParameter ("UseFilter_ID", ValueTypes.Bool));
			
			foreach (XmlMember objMember in pobjObject.Members)
			{
				strTemp = this.GenerateSPParameter (objMember);
			
				if (!string.IsNullOrEmpty (strTemp))
				{
					stbResult.Append (TextHelper.NL_1_TAB);
					stbResult.Append (",");
					stbResult.Append (strTemp);
					
					// Si el valor asignado sera null el parmetro correspondiente no se usa, de lo contrario se evalua
					// para determinar como se usara: 0 = Equals, 1 = LIKE% 
					stbResult.Append (TextHelper.NL_1_TAB);
					stbResult.Append (",");
					
					stbResult.Append (this.GenerateSPParameterUseFilter (objMember));
				}
			}
			
			return stbResult.ToString ();
		}
		
		
		private string GenerateObjectConditionsConcat (XmlObject pobjObject)
		{
			string strTemp;
		
			StringBuilder stbResult;
			
			
			stbResult = new StringBuilder ();
		
			stbResult.Append (TextHelper.NL_2_TAB);
			stbResult.AppendLine ("SET @pID = pID;");
			
			// Equals
			stbResult.Append (TextHelper.NL_1_TAB);
			stbResult.AppendFormat ("IF {0}pUseFilter_ID = 0 THEN", this.ParamsSeparator);
			stbResult.Append (TextHelper.NL_2_TAB);
			// ? => pID
			stbResult.AppendFormat ("SET @strQuery = CONCAT (@strQuery, ' AND {0}{1}{0}.{0}ID{0} = ?');", 
				this.NamesSeparator, pobjObject.Alias);
			
			// LIKE
			stbResult.Append (TextHelper.NL_1_TAB);
			stbResult.AppendFormat ("ELSEIF {0}pUseFilter_ID > 0 THEN", this.ParamsSeparator);
			stbResult.Append (TextHelper.NL_2_TAB);
			// ? => pID
			stbResult.AppendFormat ("SET @strQuery = CONCAT (@strQuery, ' AND {0}{1}{0}.{0}ID{0} LIKE ?');", 
				this.NamesSeparator, pobjObject.Alias);
			
			// Parche
			stbResult.Append (TextHelper.NL_1_TAB);
			stbResult.Append ("ELSE");
			// ? ? => pID
			stbResult.Append (TextHelper.NL_2_TAB);
			stbResult.Append ("SET @strQuery = CONCAT (@strQuery, ' AND ? IS NULL');");			
			stbResult.Append (TextHelper.NL_1_TAB);
			stbResult.AppendLine ("END IF;");
			
			foreach (XmlMember objMember in pobjObject.Members)
			{
				if (objMember.IsCustom) { strTemp = "ID"; } else { strTemp = string.Empty; }				
			
				stbResult.Append (TextHelper.NL_2_TAB);
				stbResult.AppendFormat ("SET @p{1}{0} = p{1}{0};", objMember.Name, strTemp);
				stbResult.AppendLine ();
			
				// Equals
				stbResult.Append (TextHelper.NL_1_TAB);
				stbResult.AppendFormat ("IF {0}pUseFilter_{2}{1} = 0 THEN", 
					this.ParamsSeparator, objMember.Name, strTemp);
				stbResult.Append (TextHelper.NL_2_TAB);
				// ? ? => pX
				stbResult.AppendFormat ("SET @strQuery = CONCAT (@strQuery, ' AND {0}{1}{0}.{0}{3}{2}{0} = ?');", 
					this.NamesSeparator, pobjObject.Alias, objMember.Name, strTemp);
				
				// LIKE
				stbResult.Append (TextHelper.NL_1_TAB);
				stbResult.AppendFormat ("ELSEIF {0}pUseFilter_{2}{1} > 0 THEN", 
					this.ParamsSeparator, objMember.Name, strTemp);
				stbResult.Append (TextHelper.NL_2_TAB);
				// ? ? => pX
				stbResult.AppendFormat ("SET @strQuery = CONCAT (@strQuery, ' AND {0}{1}{0}.{0}{3}{2}{0} LIKE ?');", 
					this.NamesSeparator, pobjObject.Alias, objMember.Name, strTemp);
				
				// Parche
				stbResult.Append (TextHelper.NL_1_TAB);
				stbResult.Append ("ELSE");
				// ? ? => pX
				stbResult.Append (TextHelper.NL_2_TAB);
				stbResult.Append ("SET @strQuery = CONCAT (@strQuery, ' AND ? IS NULL');");			
				stbResult.Append (TextHelper.NL_1_TAB);
				stbResult.AppendLine ("END IF;");
			}
			
			return stbResult.ToString ();
		}


		//protected override void AddCreateSPCount (XmlObject pobjObject)
		//{
		//    this.AddStartSP (pobjObject, "Count");
			
		//    this._Writer.Write (this.GenerateObjectParameters (pobjObject));
			
		//    this._Writer.WriteLine (TextHelper.NL_PC);
			
		//    this._Writer.WriteLine ("BEGIN");
			
		//    this._Writer.Write (TextHelper.NL_1_TAB);
			
		//    this._Writer.WriteLine ("SET @strQuery = 'SELECT COUNT (ID) AS {1}{2}_Count{1} FROM {0} AS {1}{2}{1} WHERE 1 = 1';", 
		//        this.GenerateTableName (pobjObject), this.NamesSeparator, pobjObject.Alias);
			
		//    this._Writer.Write (this.GenerateObjectConditionsConcat (pobjObject));
			
		//    this._Writer.Write (TextHelper.NL_1_TAB);
		//    this._Writer.Write ("PREPARE QUERY FROM @strQuery;");
		//    this._Writer.Write (TextHelper.NL_1_TAB);
		//    this._Writer.Write ("EXECUTE QUERY;");
			
		//    this.AddEndSP ();
		//}


		protected override void AddCreateSPSelect(XmlObject pobjObject)
		{	
			string strTemp;
			
		
			this.AddStartSP (pobjObject, "Select");
			
			this._Writer.Write (this.GenerateObjectParameters (pobjObject));
			
			// Parametros de Paginación
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write (",");
			this._Writer.Write (this.GenerateSPParameter ("PageOffSet", ValueTypes.UInt32));
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write (",");
			this._Writer.Write (this.GenerateSPParameter ("PageRowCount", ValueTypes.UInt32));
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write (",");
			this._Writer.Write (this.GenerateSPParameter ("CustomFields", ValueTypes.String));
			
			this._Writer.WriteLine (TextHelper.NL_PC);
			
			this._Writer.WriteLine ("BEGIN");
			
			#region Columnas de Salida
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.WriteLine ("SET @strQuery = 'SELECT ';");
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("IF {0}pCustomFields IS NOT NULL THEN", this.ParamsSeparator);
				this._Writer.Write (TextHelper.NL_2_TAB);
				this._Writer.Write ("SET @strQuery = CONCAT (@strQuery, {0}pCustomFields);", this.ParamsSeparator);
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.WriteLine ("ELSE");
				this._Writer.Write (TextHelper.NL_2_TAB);
				this._Writer.Write ("SET @strQuery = CONCAT (@strQuery, '");
				this._Writer.Write ("{0}ID{0} AS {0}{1}_ID{0},", this.NamesSeparator, pobjObject.Alias);
				this._Writer.Write (this.GenerateListColumns (pobjObject));
				this._Writer.WriteLine ("');");
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.WriteLine ("END IF;");
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("SET @strQuery = CONCAT (@strQuery, '");
			this._Writer.Write (" FROM {0} AS {1}{2}{1}", this.GenerateTableName (pobjObject), this.NamesSeparator, pobjObject.Alias);
			this._Writer.WriteLine (" WHERE 1 = 1');");
			
			#endregion
			
			this._Writer.Write (this.GenerateObjectConditionsConcat (pobjObject));
			
			#region Ajuste de parametros Limit
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.WriteLine ("SET @strTemp = '';");
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("IF pPageOffSet IS NOT NULL THEN");
			this._Writer.Write (TextHelper.NL_2_TAB);
			this._Writer.WriteLine ("SET @strTemp = CONCAT (@strTemp, ' LIMIT ?');");
			this._Writer.Write (TextHelper.NL_2_TAB);
			this._Writer.Write ("IF pPageRowCount IS NOT NULL THEN");
			this._Writer.Write (TextHelper.NL_3_TAB);
			this._Writer.Write ("SET @strTemp = CONCAT (@strTemp, ', ?');");
			this._Writer.Write (TextHelper.NL_2_TAB);
			this._Writer.Write ("ELSE");
			this._Writer.Write (TextHelper.NL_3_TAB);
			this._Writer.Write ("SET pPageRowCount = pPageOffSet;");
			this._Writer.Write (TextHelper.NL_3_TAB);
			this._Writer.Write ("SET @strTemp = CONCAT (' AND ? IS NULL', @strTemp);");
			this._Writer.Write (TextHelper.NL_2_TAB);
			this._Writer.Write ("END IF;");
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("ELSE");
			this._Writer.Write (TextHelper.NL_2_TAB);
			this._Writer.Write ("SET @strTemp = CONCAT (@strTemp, ' AND ? IS NULL AND ? IS NULL');");
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.WriteLine ("END IF;");
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("SET @strQuery = CONCAT (@strQuery, @strTemp);");
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("SET {0}intPageOffSet = pPageOffSet;", this.VarsSeparator);
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("SET {0}intPageRowCount = pPageRowCount;", this.VarsSeparator);
			
			#endregion
			
			this._Writer.WriteLine ();
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("PREPARE QUERY FROM @strQuery;");
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("EXECUTE QUERY USING @pID");
			
			foreach (XmlMember objMember in pobjObject.Members)
			{
				if (objMember.IsCustom) { strTemp = "ID"; } else { strTemp = string.Empty; }
				
				// this._Writer.Write (", {0}pUseFilter_{1}{2}", this.VarsSeparator, strTemp, objMember.Name);
				this._Writer.Write (", {0}p{1}{2}", this.VarsSeparator, strTemp, objMember.Name);				
			}
			
			this._Writer.Write (", @intPageOffSet, @intPageRowCount;");
			
			this.AddEndSP ();
		}

		protected override void AddCreateSPDeleteByID(XmlObject pobjObject)
		{
			this.AddStartSP (pobjObject, "DeleteByID");
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			
			this._Writer.Write (this.GenerateSPParameterID (pobjObject.IDType, pobjObject.IDMaxLength));
			
			this._Writer.WriteLine (TextHelper.NL_PC);
			this._Writer.WriteLine ("BEGIN");
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("DELETE FROM {0} WHERE ID = {1}pID;", this.GenerateTableName (pobjObject), this.ParamsSeparator);
			
			this.AddEndSP ();
		}

		//protected override void AddCreateSPSelectByID(XmlObject pobjObject)
		//{
		//    this.AddStartSP (pobjObject, "SelectByID");
			
		//    this._Writer.Write (TextHelper.NL_1_TAB);
			
		//    this._Writer.Write (this.GenerateSPParameterID (pobjObject.IDType, pobjObject.IDMaxLength));
			
		//    this._Writer.WriteLine (TextHelper.NL_PC);
		//    this._Writer.WriteLine ("BEGIN");
			
		//    this._Writer.Write (TextHelper.NL_1_TAB);
		//    this._Writer.Write ("SELECT");
		//    this._Writer.Write (this.GenerateListColumns (pobjObject));
		//    this._Writer.Write (TextHelper.NL_1_TAB);
		//    this._Writer.Write ("FROM {0} AS {1}{2}{1}", this.GenerateTableName (pobjObject), this.NamesSeparator, pobjObject.Alias);
		//    this._Writer.Write (TextHelper.NL_1_TAB);
		//    this._Writer.Write ("WHERE ID = {0}pID;", this.ParamsSeparator);
			
		//    this.AddEndSP ();
		//}

		
		protected override void AddCreateSPSelectList (XmlObject pobjObject)
		{
			if (!pobjObject.HasNameMember) { return; }
			
		
			this.AddStartSP (pobjObject, "SelectList");
			this._Writer.Write (TextHelper.NL_PC);
			
			#region Contenidos
			
			this._Writer.WriteLine ("BEGIN");
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("SELECT");
			this._Writer.Write (TextHelper.NL_2_TAB);
			this._Writer.Write ("{0}ID{0} AS {0}{1}_ID{0}", this.NamesSeparator, pobjObject.Alias);
			this._Writer.Write (TextHelper.NL_2_TAB);
			this._Writer.Write (",{0}{1}{0} AS {0}{2}_{3}{0}", this.NamesSeparator, pobjObject.NameMember.Name, pobjObject.Alias, pobjObject.NameMember.Alias);
			
			if (pobjObject.HasAbreviatureMember)
			{
				this._Writer.Write (TextHelper.NL_2_TAB);
				this._Writer.Write (",{0}{1}{0} AS {0}{2}_{3}{0}", this.NamesSeparator, pobjObject.AbreviatureMember.Name, pobjObject.Alias, pobjObject.AbreviatureMember.Alias);
			}
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("FROM");
			this._Writer.Write (TextHelper.NL_2_TAB);
			this._Writer.Write ("{0} AS {1}{2}{1}", this.GenerateTableName (pobjObject), this.NamesSeparator, pobjObject.Alias);
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("ORDER BY {0}{1}{0}.{0}{2}{0};", this.NamesSeparator, pobjObject.Alias, pobjObject.NameMember.Name);
			
			#endregion
			
			this.AddEndSP ();
		}
		
		
		protected override void AddCreateSPSelectEnabledList (XmlObject pobjObject)
		{
			if (!pobjObject.HasEnabledMember) { return; }
		
			if (!pobjObject.HasNameMember) { return; }
			
		
			this.AddStartSP (pobjObject, "SelectEnabledList");
			this._Writer.Write (TextHelper.NL_PC);
			
			#region Contenidos
			
			this._Writer.WriteLine ("BEGIN");
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("SELECT");
			this._Writer.Write (TextHelper.NL_2_TAB);
			this._Writer.Write ("{0}ID{0} AS {0}{1}_ID{0}", this.NamesSeparator, pobjObject.Alias);
			this._Writer.Write (TextHelper.NL_2_TAB);
			this._Writer.Write (",{0}{1}{0} AS {0}{2}_{3}{0}", this.NamesSeparator, pobjObject.NameMember.Name, pobjObject.Alias, pobjObject.NameMember.Alias);
			
			if (pobjObject.HasAbreviatureMember)
			{
				this._Writer.Write (TextHelper.NL_2_TAB);
				this._Writer.Write (",{0}{1}{0} AS {0}{2}_{3}{0}", this.NamesSeparator, pobjObject.AbreviatureMember.Name, pobjObject.Alias, pobjObject.AbreviatureMember.Alias);
			}
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("FROM");
			this._Writer.Write (TextHelper.NL_2_TAB);
			this._Writer.Write ("{0} AS {1}{2}{1}", this.GenerateTableName (pobjObject), this.NamesSeparator, pobjObject.Alias);
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("WHERE {0}{1}{0}.{0}{2}{0} = 1", this.NamesSeparator, pobjObject.Alias, pobjObject.EnabledMember.Name);
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("ORDER BY {0}{1}{0}.{0}{2}{0};", this.NamesSeparator, pobjObject.Alias, pobjObject.NameMember.Name);
			
			#endregion
			
			this.AddEndSP ();
		}
		
		
		protected override void AddCreateSPInsertUpdate (XmlObject pobjObject)
		{	
			bool blnAddedFirst;
			string strTemp;
			
			
			this.AddStartSP (pobjObject, "InsertUpdate");
			
			#region Parametros
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write (this.GenerateSPParameterID (pobjObject.IDType, pobjObject.IDMaxLength, ParameterDirection.InputOutput));
			
			foreach (XmlMember objMember in pobjObject.Members)
			{
				this._Writer.Write (TextHelper.NL_1_TAB);
				this._Writer.Write (",{0}", this.GenerateSPParameter (objMember));
			}
			
			this._Writer.WriteLine (TextHelper.NL_PC);
			
			#endregion
			
			#region Contenidos
			
			this._Writer.WriteLine ("BEGIN");
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.WriteLine ("IF EXISTS (SELECT 1 FROM {1} WHERE ID = {0}pID) THEN", 
				this.ParamsSeparator, this.GenerateTableName (pobjObject));
			
			#region Update
			
			this._Writer.Write (TextHelper.NL_2_TAB);
			this._Writer.Write ("UPDATE {0} SET", this.GenerateTableName (pobjObject));
			
			#region Columnas
			
			blnAddedFirst = false;
			
			foreach (XmlMember objMember in pobjObject.Members)
			{
				strTemp = this.GenerateColumnName (objMember, true);
				
				if (!string.IsNullOrEmpty (strTemp))
				{
					this._Writer.Write (TextHelper.NL_3_TAB);
					
					if (blnAddedFirst) { this._Writer.Write (","); }
					
					this._Writer.Write (strTemp);
					this._Writer.Write (this.GenerateSPParameterName (objMember));
					blnAddedFirst = true;
				}
			}
			
			#endregion
			
			this._Writer.Write (TextHelper.NL_2_TAB);
			this._Writer.WriteLine ("WHERE ID = {0}pID;", this.ParamsSeparator);
			
			#endregion
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.WriteLine ("ELSE");
			
			#region Insert
			
			this._Writer.Write (TextHelper.NL_2_TAB);
			this._Writer.Write ("INSERT INTO {0}", this.GenerateTableName (pobjObject));
			this._Writer.Write (TextHelper.NL_2_TAB_PO);
			
			#region Columnas
			
			blnAddedFirst = false;
			
			foreach (XmlMember objMember in pobjObject.Members)
			{
				strTemp = this.GenerateColumnName (objMember, false);
				
				if (!string.IsNullOrEmpty (strTemp))
				{
					this._Writer.Write (TextHelper.NL_3_TAB);
					
					if (blnAddedFirst) { this._Writer.Write (","); }
				
					this._Writer.Write (strTemp);
					blnAddedFirst = true;
				}
			}
			
			#endregion
			
			this._Writer.Write (TextHelper.NL_2_TAB_PC);
			this._Writer.Write (TextHelper.NL_2_TAB);
			this._Writer.Write ("VALUES");
			this._Writer.Write (TextHelper.NL_2_TAB_PO);
			
			#region Parametros de Columnas
			
			blnAddedFirst = false;
			
			foreach (XmlMember objMember in pobjObject.Members)
			{
				strTemp = this.GenerateSPParameterName (objMember);
				
				if (!string.IsNullOrEmpty (strTemp))
				{
					this._Writer.Write (TextHelper.NL_3_TAB);
				
					if (blnAddedFirst) { this._Writer.Write (","); }
				
					this._Writer.Write (strTemp);
					blnAddedFirst = true;
				}
			}
			
			#endregion
			
			this._Writer.Write (TextHelper.NL_2_TAB_PC);
			this._Writer.WriteLine (";");
			 
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.WriteLine ("SET {0}pID = (SELECT LAST_INSERT_ID ());", this.ParamsSeparator); 
			
			#endregion
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("END IF;");
			
			#endregion
			
			this.AddEndSP ();
		}


		protected override void AddCreateSPInsertArray (XmlObject pobjObject, XmlMember pobjMember, XmlObject pobjExtRefObject)
		{
			this.AddStartSP (pobjObject, "Insert_ArrayOf" + pobjMember.Alias);
			
			#region Parametros
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write (this.GenerateSPParameterID ("ID" + pobjObject.Name, pobjObject.IDType, pobjObject.IDMaxLength));
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write (",");
			this._Writer.Write (this.GenerateSPParameterID ("ID" + pobjExtRefObject.Name, pobjExtRefObject.IDType, pobjExtRefObject.IDMaxLength));
			
			#endregion
			
			this._Writer.WriteLine (TextHelper.NL_PC);
			this._Writer.WriteLine ("BEGIN");
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("INSERT INTO {0}", this.GenerateTableNameForRefArray (pobjObject, pobjMember, pobjExtRefObject));
						
			#region Columnas
			
			this._Writer.Write (TextHelper.NL_1_TAB_PO);
			this._Writer.Write (TextHelper.NL_2_TAB);
			this._Writer.Write ("ID{0}, ID{1}", pobjObject.Name, pobjExtRefObject.Name);
			this._Writer.Write (TextHelper.NL_1_TAB_PC);
			
			#endregion
			
			#region Valores
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("VALUES");
			this._Writer.Write (TextHelper.NL_1_TAB_PO);
			this._Writer.Write (TextHelper.NL_2_TAB);
			this._Writer.Write ("{0}pID{1}, {0}pID{2}", this.ParamsSeparator, pobjObject.Name, pobjExtRefObject.Name);
			this._Writer.Write (TextHelper.NL_1_TAB_PC);
			this._Writer.WriteLine (";");
			
			#endregion
			
			this.AddEndSP ();
		}

		protected override void AddCreateSPDeleteArrayByRef (XmlObject pobjObject, XmlMember pobjMember, XmlObject pobjExtRefObject)
		{
			this.AddStartSP (pobjObject, "Delete_ArrayOf" + pobjMember.Alias + "By" + pobjExtRefObject.Alias);
			
			#region Parametros
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write (this.GenerateSPParameterID ("ID" + pobjExtRefObject.Name, pobjExtRefObject.IDType, pobjExtRefObject.IDMaxLength));
			
			#endregion
			
			this._Writer.WriteLine (TextHelper.NL_PC);
			this._Writer.WriteLine ("BEGIN");
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("DELETE FROM {0} WHERE ID{1} = pID{1};", 
				this.GenerateTableNameForRefArray (pobjObject, pobjMember, pobjExtRefObject), pobjExtRefObject.Name);
			
			this.AddEndSP ();
		}
		
		protected override void AddCreateSPDeleteArrayBySelf (XmlObject pobjObject, XmlMember pobjMember, XmlObject pobjExtRefObject)
		{
			this.AddStartSP (pobjObject, "Delete_ArrayOf" + pobjMember.Alias + "By" + pobjObject.Alias);
			
			#region Parametros
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write (this.GenerateSPParameterID ("ID" + pobjObject.Name, pobjObject.IDType, pobjObject.IDMaxLength));
			
			#endregion
			
			this._Writer.WriteLine (TextHelper.NL_PC);
			this._Writer.WriteLine ("BEGIN");
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("DELETE FROM {0} WHERE ID{1} = pID{1};", 
				this.GenerateTableNameForRefArray (pobjObject, pobjMember, pobjExtRefObject), pobjObject.Name);
			
			this.AddEndSP ();
		}

		protected override void AddCreateSPSelectRefArrayByMe (XmlObject pobjObject, XmlMember pobjMember, XmlObject pobjExtRefObject)
		{
			this.AddStartSP (pobjObject, "SelectRefArrayOf_" + pobjMember.Alias + "_By_" + pobjObject.Alias);
			
			#region Parametros
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write (this.GenerateSPParameterID (pobjObject));
			
			#endregion
			
			this._Writer.WriteLine (TextHelper.NL_PC);
			this._Writer.WriteLine ("BEGIN");
			
			#region Consulta
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("SELECT");
			this._Writer.Write (this.GenerateListColumns (pobjExtRefObject));
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("FROM {0} AS {1}{2}{1}", 
				this.GenerateTableName (pobjExtRefObject), this.NamesSeparator, pobjExtRefObject.Alias);
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("INNER JOIN {0} AS {1}AxB{1}", 
				this.GenerateTableNameForRefArray (pobjObject, pobjMember, pobjExtRefObject), this.NamesSeparator);
			this._Writer.Write (TextHelper.NL_2_TAB);
			this._Writer.Write ("ON {1}.{0}ID{0} = {0}AxB{0}.{0}ID{2}{0}", 
				this.NamesSeparator, pobjExtRefObject.Alias, pobjExtRefObject.Name);
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("WHERE {0}AxB{0}.{0}ID{1}{0} = {2}pID{1};", 
				this.NamesSeparator, pobjObject.Name, this.ParamsSeparator);
			
			#endregion
			
			this.AddEndSP ();
		}

		protected override void AddCreateSPSelectArraySelfByRef (XmlObject pobjObject, XmlMember pobjMember, XmlObject pobjExtRefObject)
		{
			this.AddStartSP (pobjObject, "SelectSelfArrayOf_" + pobjObject.Alias + "_By_" + pobjMember.Alias);
			
			#region Parametros
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write (this.GenerateSPParameterID (pobjExtRefObject));
			
			#endregion
			
			this._Writer.WriteLine (TextHelper.NL_PC);
			this._Writer.WriteLine ("BEGIN");
			
			#region Consulta
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("SELECT");
			this._Writer.Write (this.GenerateListColumns (pobjObject));
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("FROM {0} AS {1}{2}{1}", 
				this.GenerateTableName (pobjObject), this.NamesSeparator, pobjObject.Alias);
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("INNER JOIN {0} AS {1}AxB{1}", 
				this.GenerateTableNameForRefArray (pobjObject, pobjMember, pobjExtRefObject), this.NamesSeparator);
			this._Writer.Write (TextHelper.NL_2_TAB);
			this._Writer.Write ("ON {1}.{0}ID{0} = {0}AxB{0}.{0}ID{2}{0}", 
				this.NamesSeparator, pobjObject.Alias, pobjObject.Name);
			
			this._Writer.Write (TextHelper.NL_1_TAB);
			this._Writer.Write ("WHERE {0}AxB{0}.{0}ID{1}{0} = {2}pID{1};", 
				this.NamesSeparator, pobjExtRefObject.Name, this.ParamsSeparator);
			
			#endregion
			
			this.AddEndSP ();
		}		
		
		#endregion
		
		#region Manejo de Parametros

		protected override string GenerateSPParameterID (string pstrBasicParameterName, IDTypes? pobjIDType, byte? pbytIDMaxLength)
		{
			return this.GenerateSPParameterID (pstrBasicParameterName, pobjIDType, pbytIDMaxLength, ParameterDirection.Input);
		}
		
		
		protected override string GenerateSPParameterID (IDTypes? pobjIDType, byte? pbytIDMaxLength)
		{
			return this.GenerateSPParameterID (null, pobjIDType, pbytIDMaxLength, ParameterDirection.Input);
		}
		
		
		protected override string GenerateSPParameterID (IDTypes? pobjIDType, byte? pbytIDMaxLength, ParameterDirection penuParameterDirection)
		{
			return this.GenerateSPParameterID (null, pobjIDType, pbytIDMaxLength, penuParameterDirection);
		}
		
				
		protected override string GenerateSPParameterID (string pstrBasicParameterName, IDTypes? pobjIDType, byte? pbytIDMaxLength, ParameterDirection penuParameterDirection)
		{
			if (string.IsNullOrEmpty (pstrBasicParameterName)) { pstrBasicParameterName = "ID"; }
		
			return string.Format ("{0} {1}", this.GenerateStartSPParameter (pstrBasicParameterName, penuParameterDirection),
				this.GenerateTraslateDbIDType (pobjIDType, pbytIDMaxLength));
		}


		protected override string GenerateSPParameterUseFilter(XmlMember pobjMember)
		{
			return this.GenerateSPParameter ("UseFilter_" + (pobjMember.IsCustom ? "ID" : string.Empty) + pobjMember.Name, ValueTypes.Byte);
		}


		protected override string GenerateSPParameter(string pstrBasicParameterName, ValueTypes pobjValueType)
		{
			return this.GenerateSPParameter (pstrBasicParameterName, pobjValueType, null);
		}


		protected override string GenerateSPParameter(string pstrBasicParameterName, ValueTypes pobjValueType, ushort? pshrMaxLength)
		{
			return this.GenerateSPParameter (pstrBasicParameterName, pobjValueType, pshrMaxLength, ParameterDirection.Input);
		}
		
		
		protected override string GenerateSPParameter(string pstrBasicParameterName, ValueTypes pobjValueType, ushort? pshrMaxLength, ParameterDirection penuParameterDirection)
		{
			return this.GenerateSPParameter (pstrBasicParameterName, pobjValueType, pshrMaxLength, penuParameterDirection, null);
		}
		

		protected override string GenerateSPParameter(string pstrBasicParameterName, ValueTypes pobjValueType, ushort? pshrMaxLength, ParameterDirection penuParameterDirection, string pstrDefaultValue)
		{
			string strParameterName;
			
			
			strParameterName = this.GenerateStartSPParameter (pstrBasicParameterName, penuParameterDirection);
		
			if (string.IsNullOrEmpty (strParameterName)) { return string.Empty; }
		
			strParameterName = string.Format ("{0} {1}", strParameterName, this.GenerateTraslateDbType (pobjValueType, pshrMaxLength, null, null));
			
			/* MySQL en su version  5.x no soporta definir valores por defecto para los parametros de un procedimiento almacenado */
			
			//if (!string.IsNullOrEmpty (pstrDefaultValue))
			//{
			//    if (pobjValueType == ValueTypes.String || pobjValueType == ValueTypes.Date || pobjValueType == ValueTypes.DateTime)
			//    {
			//        pstrDefaultValue = string.Format ("'{0}'", pstrDefaultValue);
			//    }
				
			//    return strParameterName + " = " + pstrDefaultValue;
			//}
			
			return strParameterName;
		}
		
		
		protected override string GenerateSPParameter (XmlMember pobjMember)
		{
			return this.GenerateSPParameter (pobjMember, ParameterDirection.Input);
		}
		
		
		protected override string GenerateSPParameter (XmlMember pobjMember, ParameterDirection penuParameterDirection)
		{
			return this.GenerateSPParameter (pobjMember, penuParameterDirection, null);
		}
		
		
		protected override string GenerateSPParameter (XmlMember pobjMember, ParameterDirection penuParameterDirection, string pstrDefaultValue)
		{
			string strParameter;
			
			ValueTypes enuApplicableMemberRefValueType;
			
			ushort? shrApplicableMemberRefIDMaxLength;
			
			
			this.ObjectSetManager.TraslateRefValueType (pobjMember, out enuApplicableMemberRefValueType, out shrApplicableMemberRefIDMaxLength);
			
		
			strParameter = this.GenerateSPParameter (this.GenerateSPParameterName (pobjMember, false), 
				enuApplicableMemberRefValueType, shrApplicableMemberRefIDMaxLength, penuParameterDirection, pstrDefaultValue);
			
			/* Mysql version  5.0 no soporta parametros con valores por defecto */ 
			//if (string.IsNullOrEmpty (pstrDefaultValue) && !pobjMember.Required)
			//{
			//    return strParameter + " = NULL";
			//}
			
			return strParameter;
		}
		
		
		protected override string GenerateStartSPParameter (string pstrBasicParameterName, ParameterDirection penuParameterDirection)
		{
			string strDirection;
			
			
			pstrBasicParameterName = this.GenerateSPParameterName (pstrBasicParameterName);
			
			if (string.IsNullOrEmpty (pstrBasicParameterName)) { return string.Empty; }
		
		
			switch (penuParameterDirection)
			{
				case ParameterDirection.InputOutput:
					strDirection = "INOUT ";
					break;
					
				case ParameterDirection.Output:
					strDirection = "OUT ";
					break;
				
				case ParameterDirection.ReturnValue:
					throw new NotSupportedException (string.Format ("Solo son soportados los parametros del tipo IN, OUT e INOUT: {0}", pstrBasicParameterName));
					
				default:
					strDirection = string.Empty;
					break;
			}
			
			return string.Format ("{0}{1}", strDirection, pstrBasicParameterName);
		}
		
		#endregion
		
		#endregion
	}
}